# encoding: utf-8 -*-
import time
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from common.logger import GetLogger
from get_project_path import project_path


class InitDriver():
    """
    该类的对象将会代替driver对象，并且该对象还可以发起各种操作
    """

    def __init__(self, browser='chrome'):
        self.logger = GetLogger.logger
        self.browser = browser.lower()

        if self.browser == 'chrome':
            options = webdriver.ChromeOptions()
            # options.add_argument('--incognito')   # 开启浏览器的无痕模式
            prefs = {
                'profile.default_content_setting_values':
                    {
                        'notifications': 2
                    }
            }
            options.add_experimental_option('prefs', prefs)  # 关掉浏览器左上角的通知提示
            self.driver = webdriver.Chrome(executable_path=project_path + "\data\chromedriver.exe",
                                           chrome_options=options)
        elif self.browser == 'firefox':
            self.driver = webdriver.Firefox()
        elif self.browser == 'ie':
            self.driver = webdriver.Ie()
        elif self.browser == 'edge':
            self.driver = webdriver.Edge()
        elif self.browser == 'safari':
            self.driver = webdriver.Safari()
        else:
            self.logger.error(f'不支持{self.browser}浏览器')
            raise BaseException(f'不支持{self.browser}浏览器')
        self.driver.maximize_window()  # 浏览器最大化
        self.driver.implicitly_wait(10)  # 统一的隐式等待
        # Logger.info(f'{self.browser}浏览器打开成功')
        self.logger.info(f'{self.browser}浏览器打开成功')

    # 封装各种各样的操作
    def get(self, url):
        self.driver.get(url)
        self.logger.info(f'打开目标{url}成功')

    # 本身webdriver对象就有这些动作，重新封装可以
    # 1.增加日志
    # 2.让操作能够适配框架
    def find_element(self, ele_info):
        # 每个元素的基本信息显示如下：
        # ele_info = {"name":"登录链接","type":"linktext","value":"登录","timeout":5}
        name = ele_info['name']  # 获取元素名称
        type = ele_info['type'].lower()  # 获取元素的定位类型
        value = ele_info['value']  # 获取元素定位的值
        timeout = ele_info['timeout']  # 获取元素定位的超时时间
        locator = self.get_by(ele_info)  # 获取到元组类型例子(By.ID, value)
        # element = self.driver.find_element(*locator)
        # element = self.driver.find_element(By.LINK_TEXT,'登录')
        try:
            wait = WebDriverWait(driver=self.driver, timeout=timeout)
            element = wait.until(expected_conditions.presence_of_element_located(locator))  # 显示等待
            self.logger.info(f'成功定位元素【{name}】')
        except BaseException as e:
            self.logger.exception(f'元素【{name}】未定位到,定位方式是【{type}】,值是【{value}】')
            raise BaseException(f'元素【{name}】未定位到,定位方式是【{type}】,值是【{value}】')
        return element

    def find_elements(self, ele_info):
        #
        name = ele_info['name']
        type = ele_info['type'].lower()
        value = ele_info['value']
        timeout = ele_info['timeout']
        locator = self.get_by(ele_info)

        # element = self.driver.find_element(*locator)
        try:
            wait = WebDriverWait(driver=self.driver, timeout=timeout)
            ele_list = wait.until(expected_conditions.presence_of_all_elements_located(locator))
            self.logger.info(f'成功定位到元素【{name}】,个数是{len(ele_list)}个')
        except BaseException as e:
            self.logger.exception(f'元素【{name}】未定位到,定位方式是【{type}】,值是【{value}】')
            raise BaseException(f'元素【{name}】未定位到,定位方式是【{type}】,值是【{value}】')
        return ele_list

    def get_by(self, ele_info):  # 返回元组
        type = ele_info['type'].lower()  # 获取元素的定位类型
        value = ele_info['value']  # 获取元素定位的值
        # 根据得到的元素的定位类型来得到他的定位对象
        if type == 'id':
            locator = (By.ID, value)
        elif type == 'name':
            locator = (By.NAME, value)
        elif type == 'classname':
            locator = (By.CLASS_NAME, value)
        elif type == 'tagname':
            locator = (By.TAG_NAME, value)
        elif type == 'linktext':
            locator = (By.LINK_TEXT, value)
        elif type == 'partiallinktext':
            locator = (By.PARTIAL_LINK_TEXT, value)
        elif type == 'css':
            locator = (By.CSS_SELECTOR, value)
        elif type == 'xpath':
            locator = (By.XPATH, value)
        else:
            self.logger.error(f'定位类型【{type}】不支持')
            raise BaseException(f'定位类型【{type}】不支持')
        return locator

    def click(self, ele_info):
        name = ele_info['name']  # 获取元素名称
        type = ele_info['type'].lower()  # 获取元素的定位类型
        value = ele_info['value']  # 获取元素定位的值
        timeout = ele_info['timeout']  # 获取元素定位的超时时间
        locator = self.get_by(ele_info)
        try:
            wait = WebDriverWait(driver=self.driver, timeout=timeout)
            wait.until(element_click_success(locator))
            self.logger.info(f'成功点击元素【{name}】')
        except BaseException as e:
            self.logger.exception(f'点击元素【{name}】失败,通过【{type}】方式,值是【{value}】')
            raise BaseException(f'点击元素【{name}】失败,通过【{type}】方式,值是【{value}】')

    def send_keys(self, ele_info, text):
        name = ele_info['name']
        element = self.find_element(ele_info)
        element.clear()
        element.send_keys(text)
        self.logger.info(f'向元素【{name}】传入【{text}】成功')

    def file_send_keys(self, ele_info, *value):
        name = ele_info['name']
        element = self.find_element(ele_info)
        element.send_keys(value)
        # self.logger.info(f'向元素【{name}】上传文件成功')
        self.logger.info(f'向元素【{name}】上传文件成功')

    def page_source(self):
        return self.driver.page_source

    def switch_to(self):
        return self.driver.switch_to()

    def page_contains(self, text, timeout=5):
        wait = WebDriverWait(driver=self.driver, timeout=timeout)
        try:
            wait.until(lambda d: text in d.page_source)  # d表示driver浏览器驱动
            return True
        except:
            return False

    def text_equal(self, text1, text2):
        try:
            if text1 == text2:
                return True
        except:
            return False

    def text_unequal(self, text1, text2):
        try:
            if text1 != text2:
                return True
        except:
            return False

    def clear(self, ele_info):
        element = self.find_element(ele_info)
        element.clear()

    def move_to_element(self, ele_info):
        element = self.find_element(ele_info)
        action = ActionChains(self.driver)
        action.move_to_element(element).perform()

    def swith_to_window(self, index=1):
        window_handles = self.driver.window_handles
        try:
            self.driver.switch_to.window(window_handles[index])
        except Exception as e:
            raise BaseException(f'切换窗口异常:{e}')

    # 关闭当前浏览器中的多余窗口，直到只剩下最后一个
    def close_until_one_window(self):
        # 得到当前所有的句柄
        window_handles = self.driver.window_handles
        # 遍历要关闭的多个窗口句柄，我们把第一个窗口句柄作为最后留下来的
        for i in range(1, len(window_handles)):
            # 挨个把driver切换过去，然后关闭当前界面
            self.driver.switch_to.window(window_handles[i])
            self.driver.close()  # 关闭当前窗口
        # 把driver切换至第一个窗口上
        self.driver.switch_to.window(window_handles[0])

    def switch_to_frame(self, frame_reference):
        self.driver.switch_to.frame(frame_reference)

    def dismiss(self):
        self.driver.switch_to.alert.dismiss()

    def accept(self):
        self.driver.switch_to.alert.accept()

    # def w3c(self):
    #     self.driver.w3c()

    def quit(self):
        self.driver.quit()

    def get_screenshot_as_png(self):
        # 得到的是截图的一个二进制对象，并不会存储文件到本地
        return self.driver.get_screenshot_as_png()

    def get_screenshit_as_file(self, filename):
        # 得到一个截图并作为一个文件保存起来
        self.driver.get_screenshot_as_file(filename)

    def get_text(self, ele_info):
        element = self.find_element(ele_info)
        return element.text

    def get_attribute(self, ele_info, attr_name):
        element = self.find_element(ele_info)
        return element.get_attribute(attr_name)

    def get_element_click(self, key):
        # 使用该方法前，需要确定该点能否通过xpath的text方法定位
        self.driver.find_element(By.XPATH, f'//*[text()="{key}"]').click()


class element_click_success(object):
    """ 点击直到成功."""

    def __init__(self, locator):
        self.locator = locator

    def __call__(self, driver):
        try:
            element = driver.find_element(*self.locator)  # locator是元组，*将元组拆开成多个数据
            element.click()
            # return True
            return element
        except:
            # 如果定位或者点击有异常，那么返回False，表示条件不满足，会在超时时间返回内继续轮询执行__call__里的代码
            print('点击异常，继续查找点击')
            return False


# 专门定义一个类属性，用来当做全局的driver对象
class GlobalDriver:
    globalDriver: InitDriver = None


if __name__ == '__main__':
    # driver = InitDriver()  # 默认chrome浏览器
    # driver.get('https://im.ygsoft.com/testing/ecs/mapp/manage/pc/microLearning/admin.html#/login')
    # ele_info = {"name": "用户名输入框", "type": "css", "value": 'input[autocomplete="off"][placeholder="用户名"]', "timeout": 5}
    # driver.send_keys(ele_info, '13557037903')
    # ele_info = {"name": "密码输入框", "type": "xpath", "value": '//input[@autocomplete="new-password"]', "timeout": 5}
    # driver.send_keys(ele_info, '1234.abcde')
    # ele_info = {"name": "登录按钮", "type": "xpath", "value": '//span[text()="登录"]/..', "timeout": 5}
    # driver.click(ele_info)
    # time.sleep(3)
    # driver.dismiss()
    # driver.current_url = 'https://im.ygsoft.com/testing/ecs/mapp/manage/pc/microLearning/admin.html#/homePage/learning/signUpManage?pageTitle=报名管理'
    # ele_info = {"name": "新增按钮", "type": "xpath", "value": '//span[text()="新增"]', "timeout": 5}
    # driver.click(ele_info)
    # ele_info = {"name": "新增考试报名", "type": "xpath", "value": '//li[text()="考试报名"]', "timeout": 5}
    # driver.click(ele_info)
    def get_element_click(key):
        driver = webdriver.Chrome("D:\project\webautomate\data\chromedriver.exe")
        driver.find_element_by_xpath(f"//*[@text='{key}']").click()
        print(f"//*[@text='{key}']")
    get_element_click('自动化')
